﻿
using MetroNextTools.NBase;
using MetroNextTools.NEventArgs;
using MetroNextTools.NPanel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
namespace MetroNextTools.NData
{
    public sealed class NItemContainerGenerator : INRecyclingItemContainerGenerator,ICollectionChangedListener,INNotifyItemsChanged
    {
        internal class ContainerInfo
        {
            public DependencyObject _container;
            public bool _isBusy;
        }

        #region Fields

        private WeakCollectionChangedListener _collectionChangedListener;
        private IList _items;
        private INGeneratorHost _host;
        private NGeneratorPosition _generatorPostion;
        private GeneratorDirection _generatorDirection;

        private List<ContainerInfo> _recyclableContainers = new List<ContainerInfo>();

       
        #endregion

        #region Constructor

        internal NItemContainerGenerator(INGeneratorHost host)
        {
            _host = host;
            this._items = host.Items;//这个是NItemsControl里的NCollection items 集合
            this._collectionChangedListener = WeakCollectionChangedListener.CreateIfNecessary(this._items, this);
        }

        #endregion

        #region Properties
        internal IList Items
        {
            get { return _items; }
            set
            {
                
                if (value != this._items)
                {
                    if (this._collectionChangedListener != null)
                    {
                        _collectionChangedListener.Disconnect();
                        _collectionChangedListener = null;
                    }
                    _items = value;
                    this._collectionChangedListener = WeakCollectionChangedListener.CreateIfNecessary(this._items, this);
                }
            }
        }

        private INGeneratorHost Host
        {
            get { return _host; }
        }

        private NCollectionPanel ItemsPanel
        {
            get { return _host.ItemsHost; }
        }
        #endregion

        #region DependencyProeprty

        internal static readonly DependencyProperty ItemForItemContainerProperty =
            DependencyProperty.RegisterAttached("ItemForItemContainer", typeof(object), typeof(NItemContainerGenerator), new PropertyMetadata(null));
        
        #endregion

        #region Method

        public void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    this.OnItemAdded(e.NewItems[0], e.NewStartingIndex);
                    return;
                case NotifyCollectionChangedAction.Remove:
                    this.OnItemRemoved(e.OldItems[0], e.OldStartingIndex, false);
                    return;
                case NotifyCollectionChangedAction.Replace:
                    this.OnItemReplaced(e.OldItems[0], e.NewItems[0], e.NewStartingIndex);
                    return;
                case NotifyCollectionChangedAction.Reset:
                    this.OnRefresh();
                    return;
                case NotifyCollectionChangedAction.Move:
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// 刷新
        /// </summary>
        private void OnRefresh()
        {
            this.RemoveAll();
            if (this.ItemsChanged != null)
            {
                NGeneratorPosition generatorPosition = new NGeneratorPosition(0);
                this.ItemsChanged(this, new NItemsChangedEventArgs(NotifyCollectionChangedAction.Reset, generatorPosition, 0, 0));
            }

            if (this.Items.Count != 0)
            {
                for (int i = 0; i < Items.Count; i++)
                {
                    this.OnItemAdded(Items[i], i);
                }
            }
        }

        /// <summary>
        /// Add New Items
        /// </summary>
        /// <param name="item"></param>
        /// <param name="index"></param>
        /// <param name="supressEvent"></param>
        private void OnItemAdded(object item, int index)
        {
            Rect containerRect;
            if (item is INRaitoItem)
            {
                containerRect = ItemsPanel.CaculatePosition((INRaitoItem)item);
            }
            else
            {
                //TODO 对于没有比例形式的进行处理
            }
            NGeneratorPosition position = new NGeneratorPosition(index,containerRect);
            if (this.ItemsChanged != null)
            {
                this.ItemsChanged(this, new NItemsChangedEventArgs(NotifyCollectionChangedAction.Add, position, 1, 0));
            }
        }
        
        /// <summary>
        /// Remove Items
        /// </summary>
        /// <param name="item"></param>
        /// <param name="index"></param>
        /// <param name="raiseReplaceInsteadOfRemove"></param>
        private void OnItemRemoved(object item, int index, bool raiseReplaceInsteadOfRemove)
        {


        }

        /// <summary>
        /// Replace Item
        /// </summary>
        /// <param name="oldItem"></param>
        /// <param name="newItem"></param>
        /// <param name="index"></param>
        private void OnItemReplaced(object oldItem, object newItem, int index)
        {

        }

        /// <summary>
        /// 设置Container的DataContext
        /// </summary>
        /// <param name="container"></param>
        /// <param name="item"></param>
        private void LinkContainerToItem(DependencyObject container, object item)
        {
            container.SetValue(NItemContainerGenerator.ItemForItemContainerProperty, item);
            if (container != item)
            {
                container.SetValue(FrameworkElement.DataContextProperty, item);
                container.SetValue(FrameworkElement.HeightProperty, _generatorPostion.ContainerRect.Height);
                container.SetValue(FrameworkElement.WidthProperty, _generatorPostion.ContainerRect.Width);
                container.SetValue(Canvas.LeftProperty, _generatorPostion.ContainerRect.Left);
                container.SetValue(Canvas.TopProperty, _generatorPostion.ContainerRect.Top);
            }
        }

        /// <summary>
        /// 取消Container 的 DataContext
        /// </summary>
        /// <param name="container"></param>
        /// <param name="item"></param>
        private void UnLinkContainerFromItem(DependencyObject container, object item)
        {
            container.ClearValue(NItemContainerGenerator.ItemForItemContainerProperty);
            if (container != item)
            {
                container.ClearValue(FrameworkElement.DataContextProperty);
                container.ClearValue(FrameworkElement.HeightProperty);
                container.ClearValue(FrameworkElement.WidthProperty);
                container.ClearValue(Canvas.LeftProperty);
                container.ClearValue(Canvas.TopProperty);
            }
            this._host.ClearContainerForItem(container, item);
        }
        #endregion

        #region INItemContainerGenerator Implements

        public NItemContainerGenerator GetItemContainerGeneratorForPanel(Windows.UI.Xaml.Controls.Panel panel)
        {
            throw new System.NotImplementedException();
        }

        /// <summary>
        /// 设置起始的位置
        /// </summary>
        /// <param name="position"></param>
        /// <param name="direction"></param>
        public void StartAt(NGeneratorPosition position, GeneratorDirection direction)
        {
            _generatorPostion = position;
            _generatorDirection = direction;
        }

        /// <summary>
        /// 根据其实的位置产生Container
        /// </summary>
        /// <param name="isNewRealized"></param>
        /// <returns></returns>
        public DependencyObject GenertateNext(out bool isNewRealized)
        {
            IList<object> items = (IList<object>)this._items;
            object item = items[_generatorPostion.Index];

            DependencyObject container = null;
            ContainerInfo containerInfo = _recyclableContainers.Where(x => !x._isBusy).FirstOrDefault();
            if (containerInfo != null)
            {
                container = containerInfo._container;
                container = _host.GetContainerForItem(item, container);
                isNewRealized = false;
            }
            else
            {
                if (items == null || _generatorPostion == null || _generatorDirection == null)
                {
                    throw new InvalidOperationException("The Container Can not be generated!");
                }
                container = _host.GetContainerForItem(item, container);
                containerInfo = new ContainerInfo() { _container = container, _isBusy = true };
                _recyclableContainers.Add(containerInfo);
                isNewRealized = true;
            }
            LinkContainerToItem(container, item);
            return containerInfo._container;
        }

        /// <summary>
        /// 为Container做准备
        /// </summary>
        /// <param name="container"></param>
        public void PrepareItemContainer(DependencyObject container)
        {
            object item = container.ReadLocalValue(NItemContainerGenerator.ItemForItemContainerProperty);
            this._host.PrepareItemContainer(container, item);
        }

        public void RemoveAll()
        {
            
        }

        public void Remove(NGeneratorPosition position, int count)
        {
            throw new System.NotImplementedException();
        }

        public NGeneratorPosition GeneratorPositionFromIndex(int itemIndex)
        {
            throw new System.NotImplementedException();
        }

        /// <summary>
        /// 获取当前呈现的Container的索引
        /// </summary>
        /// <param name="position"></param>
        /// <returns></returns>
        public int IndexFromGeneratorPosition(NGeneratorPosition position)
        {
            return position.Index; //TODO 这个地方需要完善
        }

        #endregion

        #region RecyclingItemContainerGenerator Implements

        public void Recycle(NGeneratorPosition position, int count)
        {
            throw new System.NotImplementedException();
        }

      

        #endregion

        public event NItemsChangedEventHandler ItemsChanged;

        event NItemsChangedEventHandler INNotifyItemsChanged.ItemsChanged
        {
            add { this.ItemsChanged += value; }
            remove { this.ItemsChanged -= value; }
        }



    }
}
